package com.wsoft.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wsoft.constant.ExcelConstant;
import com.wsoft.constant.FieldKindConstant;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.utils.ExcelDataUtil;
import com.wsoft.form.dto.WfFormTableDto;
import com.wsoft.form.entity.WfFormColumnEntity;
import com.wsoft.form.entity.WfFormDesignEntity;
import com.wsoft.form.entity.WfFormTableRelationEntity;
import com.wsoft.form.enums.FormEnum;
import com.wsoft.form.manager.WfFormColumnManager;
import com.wsoft.form.manager.WfFormDesignManager;
import com.wsoft.form.manager.WfFormTableManager;
import com.wsoft.form.manager.WfFormTableRelationManager;
import com.wsoft.form.service.impl.WfFormOperationServiceImpl;
import com.wsoft.form.util.FormUtil;
import com.wsoft.service.IExcelFormDataService;
import kotlin.Triple;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author z001
 * @Date 2024/11/11 10:33
 */
@Service
public class ExcelFormDataServiceImpl implements IExcelFormDataService {

    @Resource
    private WfFormDesignManager designManager;
    @Resource
    private WfFormTableManager formTableManager;
    @Resource
    private WfFormTableManager tableManager;
    @Resource
    private WfFormTableRelationManager relationManager;
    @Resource
    private WfFormColumnManager columnManager;
    @Resource
    private WfFormOperationServiceImpl operationService;

    /**
     * 导出自定义表单 模板 构建数据
     *
     * @param designId      设计表id
     * @param sheetNameList 多个sheet名称列表
     * @param headList      每个sheet页 表头信息
     * @param parentId      单子表导出,父节点id
     */
    @Override
    public void getExportTemplateDate(Long designId,
                                      List<String> sheetNameList,
                                      List<List<List<String>>> headList,
                                      Long parentId) {

        WfFormDesignEntity designEntity = designManager.getById(designId);
        Long tableId = designEntity.getTableId();
        Long formId = designEntity.getFormId();

        List<WfFormTableRelationEntity> list = relationManager.getByFormId(formId);
        //form下 主表id
        Long masterTableId = list.stream().filter(item -> FormEnum.ONE.getValue().equals(item.getIsMaster()))
                .map(WfFormTableRelationEntity::getTableId)
                .collect(Collectors.toList()).get(0);

        //form下 从表id集合
        List<Long> slaveTableIdList = list.stream().filter(item -> FormEnum.ZERO.getValue().equals(item.getIsMaster()))
                .map(WfFormTableRelationEntity::getTableId)
                .collect(Collectors.toList());

        if (Objects.equals(masterTableId, tableId)) {
            //导出是主表
            buildSheetInfo(masterTableId, sheetNameList, headList, true, null);
            for (Long slaveTableId : slaveTableIdList) {
                buildSheetInfo(slaveTableId, sheetNameList, headList, false, null);
            }
        } else {
            //导出子表
            if (null == parentId) {
                //单独导出子表,父id 不能为空
                Asserts.fail("[sys.export.parent.error]");
            }
            buildSheetInfo(tableId, sheetNameList, headList, false, parentId);
        }

    }

    /**
     * @param designId
     * @param dataList List<Map<Integer, Map<String, Object>>>     每个sheet的集合
     *                 Map<Integer, Map<String, Object>> 某个sheet的数据 key: 第几行  Map<String, Object> 值
     *                 Map<String, Object> key: 表头标题 value: Excel的值
     */
    @Override
    public void importExcelFormData(Long designId, List<Map<Integer, Map<String, Object>>> dataList, String parentId) {
        WfFormDesignEntity designEntity = designManager.getById(designId);
        Long formId = designEntity.getFormId();

        List<WfFormTableRelationEntity> list = relationManager.getByFormId(formId);
        //form下 主表id
        Long masterTableId = list.stream().filter(item -> FormEnum.ONE.getValue().equals(item.getIsMaster()))
                .map(WfFormTableRelationEntity::getTableId)
                .collect(Collectors.toList()).get(0);

        //form下 从表id集合
        List<Long> slaveTableIdList = list.stream().filter(item -> FormEnum.ZERO.getValue().equals(item.getIsMaster()))
                .map(WfFormTableRelationEntity::getTableId)
                .collect(Collectors.toList());

        Map<Triple<String, String, String>, Object> convertDataMap = ExcelDataUtil.getAllConvertData();

        //行号对应主表生成id map
        //key:主表行号 value:主表生成id
        Map<Object, Long> lineMap = new HashMap<>(16);
        for (int i = 0; i < dataList.size(); i++) {
            //每个sheet页的数据
            Map<Integer, Map<String, Object>> dataMap = dataList.get(i);
            if (StrUtil.isEmpty(parentId)) {
                //多个sheet页导入
                if (i == 0) {
                    //主表导入
                    importTableData(null, masterTableId, dataMap, lineMap, convertDataMap,null);
                } else {
                    //子表导入 子表有 主表行号,这边i-1
                    importTableData(formId, slaveTableIdList.get(i - 1), dataMap, lineMap, convertDataMap,null);
                }
            } else {
                //子表单独导入 单独子表 没有主表行号,这边直接取i
                importTableData(formId, slaveTableIdList.get(i), dataMap, lineMap, convertDataMap,parentId);
            }

        }

    }


    // ################################## 私有方法  ##################################

    /**
     * 构建 多sheet导出 表头信息
     *
     * @param tableId
     * @param sheetNameList
     * @param headList
     */
    public void buildSheetInfo(Long tableId, List<String> sheetNameList, List<List<List<String>>> headList, boolean isMaster, Long parentId) {
        //导出是子表
        WfFormTableDto tableInfo = tableManager.getTableInfo(tableId);
        //字段列表
        List<WfFormColumnEntity> columnList = columnManager.getColumnList(tableId);
        //查询外键关联字段
        WfFormTableRelationEntity relation = relationManager.getSlaverRelation(tableInfo.getFormId(), tableId);

        //筛选出不添加进表头的字段
        List<String> defaultColumnNameList = columnList.stream().filter(item -> {
            //筛选出 是默认 且 自动填充字段
            return FormEnum.ONE.getValue().equals(item.getIsDefault()) ||
                    (!isMaster && item.getId().equals(relation.getSlaveColumnId())) ||
                    FieldKindConstant.AUTO_FIELD_LIST.contains(item.getFieldKind());
        }).map(WfFormColumnEntity::getName).collect(Collectors.toList());


        //添加进表头的字段
        List<List<String>> headColumnList = columnList.stream().filter(item -> {
            //筛选出 不是默认 且 不自动填充字段
            return !(FormEnum.ONE.getValue().equals(item.getIsDefault()) ||
                    (!isMaster && item.getId().equals(relation.getSlaveColumnId())) ||
                    FieldKindConstant.AUTO_FIELD_LIST.contains(item.getFieldKind()));
        }).map(WfFormColumnEntity::getName).map(header -> {
            ArrayList<String> list = new ArrayList<>();
            list.add("");
            list.add(header);
            return list;
        }).collect(Collectors.toList());

        //添加默认字段,行号和主表行号,用于导入的时候
        if (isMaster) {
            headColumnList.add(0, Arrays.asList("", ExcelConstant.MASTER_NUMBER_STR));
        } else {
            if (null == parentId) {
                headColumnList.add(0, Arrays.asList("", ExcelConstant.SLAVER_NUMBER_STR));
            }
        }

        //遍历 添加表头信息
        for (int i = 0; i < headColumnList.size(); i++) {
            List<String> list = headColumnList.get(i);
            if (null != parentId) {
                //如果单独导出子表,需要添加主表id和介绍
                if (i == 0) {
                    list.set(0, StrUtil.format(ExcelConstant.TEMPLATE1, parentId));
                } else if (i == 1) {
                    list.set(0, StrUtil.format(ExcelConstant.TEMPLATE2, CollectionUtil.join(defaultColumnNameList, ",")));
                }
            } else {
                //如何是主表,第一行添加介绍
                if (i == 0) {
                    list.set(0, StrUtil.format(ExcelConstant.TEMPLATE2, CollectionUtil.join(defaultColumnNameList, ",")));
                }
            }
        }

        headList.add(headColumnList);
        //sheet信息
        sheetNameList.add(tableInfo.getTableDesc());
    }

    /**
     * 构建 导入表格数据
     *
     * @param formId
     * @param masterTableId
     * @param dataMap
     * @param lineMap
     */
    public void importTableData(Long formId, Long masterTableId,
                                Map<Integer, Map<String, Object>> dataMap,
                                Map<Object, Long> lineMap,
                                Map<Triple<String, String, String>, Object> convertDataMap,String parentId) {
        //字段列表
        List<WfFormColumnEntity> columnList = columnManager.getColumnList(masterTableId);
        //外键关联名称
        String relationColumnName = null;
        if (null != formId) {
            WfFormTableRelationEntity relation = relationManager.getSlaverRelation(formId, masterTableId);
            Long slaveColumnId = relation.getSlaveColumnId();
            relationColumnName = columnManager.getById(slaveColumnId).getColumnName();
        }

        //筛选出添加进表头的字段
        List<String> defaultColumnNameList = columnList.stream().filter(item -> {
            //筛选出 不是默认 且 不自动填充字段
            return FormEnum.ZERO.getValue().equals(item.getIsDefault()) &&
                    !FieldKindConstant.AUTO_FIELD_LIST.contains(item.getFieldKind());
        }).map(WfFormColumnEntity::getColumnName).collect(Collectors.toList());

        List<Map<String, Object>> valueMapList = new ArrayList<>();
        //行号
        List<Object> lineNumber = new ArrayList<>();

        //sheet页 每一行的数据
        List<Map<String, Object>> rowListMapData = new ArrayList<>(dataMap.values());
        for (int k = 0; k < rowListMapData.size(); k++) {
            //每一行的values集合(列)
            List<Object> rowData = new ArrayList<>(rowListMapData.get(k).values());
            Map<String, Object> valueMap = new HashMap<>(16);
            for (int j = 0; j < rowData.size(); j++) {
                //每一列的值
                Object value = rowData.get(j);
                //parentId 为空 则代表是主表导入,多sheet 多了个字段 ,行号和主表id
                if(StrUtil.isBlank(parentId)){
                    if (j == 0) {
                        if (null == formId) {
                            //行号
                            lineNumber.add(value);
                        } else {
                            Long createId = lineMap.get(value);
                            valueMap.put(relationColumnName, createId);
                        }
                    } else {
                        //数据值 j-1 去除第一个行号
                        String columnName = defaultColumnNameList.get(j - 1);
                        //转换
                        value = FormUtil.convertData(convertDataMap, columnList, columnName, value);
                        valueMap.put(columnName, value);
                    }
                }else{
                    valueMap.put(relationColumnName, parentId);
                    String columnName = defaultColumnNameList.get(j);
                    //转换
                    value = FormUtil.convertData(convertDataMap, columnList, columnName, value);
                    valueMap.put(columnName, value);
                }

            }
            valueMapList.add(valueMap);
        }

        JSONArray jsonArray = new JSONArray();
        for (Map<String, Object> map : valueMapList) {
            JSONObject jsonObject = new JSONObject(map);
            jsonArray.add(jsonObject);
        }
        List<Long> createIdList = operationService.addOperationBatch(masterTableId, jsonArray);

        //保存行号对应关系
        for (int j = 0; j < lineNumber.size(); j++) {
            lineMap.put(lineNumber.get(j), createIdList.get(j));
        }
    }



}
